from datetime import datetime

from dateutil.relativedelta import relativedelta
from flask import g, current_app
from flask_restful import Resource
from flask_restful.reqparse import RequestParser

from comment.modules import db
from comment.modules.account import Account
from comment.modules.deal_record import DealRecord
from comment.modules.funding_not_matched import Funding_not_matched
from comment.modules.invest_record import Invest_record
from comment.modules.product import Product
from comment.modules.product_rate import Product_rate
from comment.modules.user import User
from comment.utils.gen_trans_id import gen_trans_id
from financial.resources.transaction.const import DealType
from financial.resources.transaction.serializer import InvestRecordPaginateSerializer


def calculate_income(rate, amount):
    """计算每期的收益"""
    return round(rate / 100 / 12 * amount, 2)


class Invest_Resource(Resource):
    """投资记录的资源类"""

    def get(self):
        """投资记录的列表"""

        rp = RequestParser()
        rp.add_argument('start')  # 起始时间
        rp.add_argument('end')  # 结束时间
        rp.add_argument('invest_type')  # 投资类型
        rp.add_argument('curPage', required=True)  # 当前页数
        rp.add_argument('per_page', required=True)  # 每一页显示最多数据

        args = rp.parse_args()
        start = args.get('start')
        end = args.get('end')
        invest_type = 0 if args.get('invest_type') == None else int(args.get('invest_type'))
        cur_page = int(args.get('curPage'))
        page_size = int(args.get('per_page'))

        user_id = g.user_id

        # 首先得到一个查询对象
        q = Invest_record.query
        # 开始过滤，根据用户id过滤
        q = q.filter(Invest_record.pUid == user_id)
        # 第二次过滤，根据投资类型过滤
        q = q.filter(Invest_record.pStatus == invest_type)
        # 第三次过滤，根据投资类型过滤
        if start and end:
            q = q.filter(db.cast(Invest_record.pDate, db.DATE) >= db.cast(start, db.DATE)) \
                .filter(db.cast(Invest_record.pDate, db.DATE) <= db.cast(end, db.DATE))

        data = q.paginate(cur_page, page_size, error_out=False)

        data = InvestRecordPaginateSerializer(data).to_dict()
        return {'msg': 'success', 'data': data}

    def post(self):
        """新增投资或者购买理财产品"""
        rp = RequestParser()
        rp.add_argument('productId', required=True)  # 产品ID
        rp.add_argument('pAmount', required=True)  # 金额
        rp.add_argument('period', required=True)  # 期数
        # rp.add_argument('discount', required=True)  # 抵扣金额

        args = rp.parse_args()
        product_id = int(args.productId)
        p_amount = int(args.pAmount)
        period = int(args.period)
        # discount = int(args.discount)

        user_id = g.user_id
        user = User.query.filter(User.id == user_id).first()

        # 查询产品对象
        product = Product.query.filter(Product.proId == product_id).first()

        # 查询产品对于的理财收益年利率，根据产品ID and 理财的期数
        pro_rate = Product_rate.query.filter(Product_rate.productId == product_id) \
            .filter(Product_rate.month == period).first()

        # 计算每期的收益
        income = calculate_income(pro_rate.incomeRate, p_amount)

        try:
            # 修改用户的资金账户数据
            user_account_query = Account.query.filter(Account.userId == user_id)
            user_account = user_account_query.first()
            # 修改之前的账户数据
            before_balance = user_account.balance
            # 判断是否可以抵扣金额
            cur_discount = 50 if user_account.discount >= 50 else 0
            _p_amount = p_amount - cur_discount  # 得到真正要支付的金额
            if user_account.balance >= _p_amount:
                before_balance = user_account.balance
                cur_balance = user_account.balance - _p_amount
                discount_balance = user_account.discount - cur_discount
            else:
                return {'message': '账户余额不足', 'code': 20005}

            interestTotal = income * period  # 总共的利息

            # 修改数据
            user_account_query.update({
                'balance': cur_balance,
                'inverstmentA': user_account.inverstmentA + p_amount,
                'investmentW': user_account.investmentW + p_amount,
                'frozen': user_account.frozen + _p_amount,
                'interestTotal': user_account.interestTotal + interestTotal,
                'discount': discount_balance
            })

            # 新增投资记录
            # 生成投资记录的流水号
            invest_num = gen_trans_id(DealType.invest.name)
            remark = '使用了50元的代金券。' if cur_discount == 50 else '没有使用代金券'
            # 投资结束的时间
            p_end_date = datetime.now() + relativedelta(months=period)
            # 精确到投资天数
            invest_days = (p_end_date - datetime.now()).days
            invest_record = Invest_record(pProductId=product_id, pUid=user_id, pBeginDate=datetime.now(),
                                          pEndDate=p_end_date, pSerialNo=invest_num, pAmount=p_amount,
                                          pEarnings=pro_rate.incomeRate,
                                          pDeadline=period, pMonthInterest=income,
                                          pMonthlyExtractInterest=income,
                                          pAvailableBalance=user.accountInfo.balance,
                                          pFrozenMoney=_p_amount, pProductName=product.productName,
                                          pDeadlineAsDay=invest_days, username=user.username,
                                          pProspectiveEarnings=interestTotal, pStatus=0, pRemark=remark)
            db.session.add(invest_record)
            db.session.flush()

            # 新增待匹配的资金
            not_matched = Funding_not_matched(fInvestRecordId=invest_record.pId, fNotMatchedMoney=p_amount,
                                              fFoundingWeight=1, matchedStatus=0)
            db.session.add(not_matched)

            # 新增交易记录

            deal_num = gen_trans_id(DealType.invest.name)
            deal_record = DealRecord(aUserId=user_id, pId=invest_record.pId, aReceiveOrPay=1,
                                     aTransferSerialNo=deal_num,
                                     aTransferStatus=1, aBeforeTradingMoney=before_balance, aAmount=p_amount,
                                     aAfterTradingMoney=cur_balance, aDescreption='投资产品购买', aType=DealType.invest.value)
            db.session.add(deal_record)
            db.session.commit()

            return {'msg':'success','data':'成功'}
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
